package com.miron.client;

import org.cobogw.gwt.waveapi.gadget.client.*;

/**
 * Represents an integer value stored under specified key in the wave state.
 * 
 * It registers a state change listener in the wave for checking if there were
 * any changes in the value stored in the state.
 * 
 * Value is stored in the wave state on every call to
 * {@link SynchronizedInteger#setValue(int)}.
 * 
 * @author Miron Sadziak mironsadziak@gmail.com
 */
public class SynchronizedInteger {

	/**
	 * Represents the wave for storing the integer value
	 */
	private final WaveFeature waveFeature;

	/**
	 * Key under which we store the value
	 */
	private final String key;

	/**
	 * We store a value also locally so that we dont have to check the wave's
	 * state every time somebody wants to see the value.
	 */
	private int localValue = 0;

	/**
	 * This constructor takes and stores the key under which we store the value
	 * in the wave and the wave itself. It registers also a state change
	 * listener for checking if there are any changes in the stored value.
	 * 
	 * @param key
	 *            Key under which we store the value
	 * @param waveFeature
	 *            Represents the wave for storing the integer value
	 */
	public SynchronizedInteger(String key, WaveFeature waveFeature) {
		this.key = key;
		this.waveFeature = waveFeature;
		// Handler below will be triggered every time on every user when
		// somebody changes the value of the integer in the wave's state (or if
		// there is some other change of state in the gadget).
		this.waveFeature
				.addStateUpdateEventHandler(new StateUpdateEventHandler() {
					@Override
					public void onUpdate(StateUpdateEvent event) {
						// TODO: Not every change in the state concerns our
						// object. It would be probably a good idea to check if
						// we are interested in this event before performing the
						// update.
						checkForUpdates();
					}
				});
	}

	/**
	 * Checks the wave's state for the value stored in it under the given key.
	 * If there is nothing stored it leaves the local value as it is.
	 */
	private void checkForUpdates() {
		Integer checkInteger = waveFeature.getState().getInt(key);
		if (checkInteger != null) {
			localValue = checkInteger;
		}
	}

	/**
	 * Returns the local integer value.
	 * 
	 * @return local value
	 */
	public int getValue() {
		return localValue;
	}

	/**
	 * Sets the local integer value to the specified value and stores it also in
	 * the wave's state.
	 * 
	 * @param value
	 *            Integer value to store
	 */
	public void setValue(int value) {
		localValue = value;
		waveFeature.getState().submitValue(key, String.valueOf(value));
	}
}
